/**
 * @Author       : oak-c
 * @Date         : 2021-01-21 13:48:39
 * @Description  : 地理位置
 * @LastEditors  : oak-c
 * @LastEditTime : 2021-01-21 21:36:50
 * @FilePath     : /src/service/global/geo.service.ts
 */
import { GlobalGeoRepo, UserGeoRepo } from '@/entities'
import { CustomLoggerService, NRedis } from '@/modules'
import { RType } from '@/modules/redis/interface'
import { ConfigService } from '@donews/nestjs-config'
import { Injectable } from '@nestjs/common'
import request from 'umi-request'
import { sm3 } from 'sm-crypto'
import moment from 'moment'

@Injectable()
export class GlobalGeoService {
    constructor(
        private readonly globalGeoRepo: GlobalGeoRepo,
        private readonly config: ConfigService,
        private readonly logger: CustomLoggerService,
        private readonly redis: NRedis,
    ) {}

    private readonly ltApi = 'https://gwapi.10646.cn/api/LocationBasedService/V1.0'
    private readonly ltAppid = 'GKPja1Zfxd'
    private readonly ltAppSecret = '9cmbqiFqceKSgfOdvHh7ieX26kvGrG'
    private readonly amapApi = 'https://restapi.amap.com/v3'
    private readonly key = this.config.get('amap.key', '63ea73c64e74938983989f42c45734f9')

    private parseOption() {
        const time = moment()
        const timestamp = time.format('YYYY-MM-DD HH:mm:ss:SSS')
        const trans_time = time.format('YYYYMMDDHHmmSSS')
        const option: Record<string, any> = {
            app_id: this.ltAppid,
            timestamp,
            trans_id: trans_time + Math.floor(Math.random() * 899999 + 100000).toString(),
        }
        let sign = ''
        Object.keys(option)
            .sort()
            .map((k) => {
                sign += k
                sign += option[k]
            })
        sign += this.ltAppSecret
        option.token = sm3(sign)
        return option
    }

    public async lbs(msg: any) {
        const option = this.parseOption()
        option.data = {
            msid: '460069004093564', //msg.value.station,
            type: 'imsi',
            pos_mode: 'last',
        }
        const res = await request.post(this.ltApi, {
            data: option,
        })
        console.log(res)
    }

    /**
     * @description: 逆地理解析
     * @param {number} lng
     * @param {number} lat
     * @return {*}
     */
    public async regeo(lng: number, lat: number) {
        if (!lng || !lat) return null
        const location = `${lng},${lat}`
        const cache = await this.redis.get(RType.PREFIX_CACHE + 'GEO:' + location)
        if (cache) return cache
        const exiting = await this.globalGeoRepo.findOne({ lng, lat })
        if (exiting) {
            await this.redis.set(RType.PREFIX_CACHE + 'GEO:' + location, exiting, 60 * 60 * 24 * 30)
            return exiting
        }
        const { status, info, regeocode } = await request.get(this.amapApi + '/geocode/regeo', {
            params: {
                key: this.key,
                location,
            },
        })
        if (status === 1 || status === '1') {
            const { formatted_address, addressComponent } = regeocode
            const { country, province, city, district, township } = addressComponent
            const geo = {
                lng,
                lat,
                country,
                province,
                city: city ? (Array.isArray(city) ? city.join(',') : city) : province,
                district,
                township,
                address: formatted_address,
            }
            await this.globalGeoRepo.save(this.globalGeoRepo.create(geo))
            return geo
        }
        this.logger.error(`[GEO] - reGeo - ${status}:${info}`)
        return null
    }
}
